/* Copyright (c) 2023 Renmin University of China
RMDB is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
        http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

#pragma once
#include "execution_defs.h"
#include "execution_manager.h"
#include "executor_abstract.h"
#include "index/ix.h"
#include "system/sm.h"

class ProjectionExecutor : public AbstractExecutor {
private:
    std::unique_ptr<AbstractExecutor> prev_;        // 投影节点的儿子节点
    std::vector<ColMeta> cols_;                     // 需要投影的字段
    size_t len_;                                    // 字段总长度
    std::vector<size_t> sel_idxs_;

    //数量限制 用于order
    int limit_;

public:
    //修改投影构造函数 添加数量限制
    ProjectionExecutor(std::unique_ptr<AbstractExecutor> prev, const std::vector<TabCol>& sel_cols, int limit) {
        prev_ = std::move(prev);

        size_t curr_offset = 0;
        auto& prev_cols = prev_->cols();
        for (auto& sel_col : sel_cols) {
            auto pos = get_col(prev_cols, sel_col);
            sel_idxs_.push_back(pos - prev_cols.begin());
            auto col = *pos;
            col.offset = curr_offset;
            curr_offset += col.len;
            cols_.push_back(col);
        }
        len_ = curr_offset;

        limit_ = limit;
    }

    void beginTuple() override {
        prev_->beginTuple();
    }

    void nextTuple() override {
        prev_->nextTuple();
    }

    std::unique_ptr<RmRecord> Next() override {
        //limit_==-1 什么也不做
        if (limit_ != -1)
        {
            //若为0，则不能打印，若不为0，则自减
            if (limit_ == 0)
                return nullptr;
            else limit_--;
        }
        //投影列为0 直接返回
        if (sel_idxs_.size() == 0)
            return nullptr;
        //前算子没有元组 返回空
        auto pre_record = prev_->Next();
        if (pre_record == nullptr)
            return nullptr;

        auto& prev_cols = prev_->cols();
        auto proj_record = std::make_unique<RmRecord>(len_);
        //投影列的数量 逐个提取每个投影列
        size_t proj_num = cols_.size();
        for (size_t index = 0; index < proj_num; index++)
        {
            size_t pre_index = sel_idxs_[index];
            auto& pre_col = prev_cols[pre_index];
            auto& proj_col = cols_[index];
            memcpy(proj_record->data + proj_col.offset, pre_record->data + pre_col.offset, pre_col.len);
        }

        return proj_record;
    }


    std::string getType() override {
        return "ProjectionExecutor";
    }

    bool is_end() const override { return prev_->is_end(); }

    size_t tupleLen() const override { return len_; }

    Rid& rid() override { return _abstract_rid; }

    const std::vector<ColMeta>& cols() const override { return cols_; }
};